package com.example.wlzz.controller;
import com.example.wlzz.api.ConfigAPI;
import com.example.wlzz.api.FileApi;
import com.example.wlzz.constant.RedisConstant;
import com.example.wlzz.dto.TokenDTO;
import com.example.wlzz.entity.User_;
import com.example.wlzz.enums.ResultEnum;
import com.example.wlzz.form.RegisterForm;
import com.example.wlzz.form.UserForm;
import com.example.wlzz.service.SmsService;
import com.example.wlzz.service.UserService;
import com.example.wlzz.utils.CodeUtil;
import com.example.wlzz.utils.MD5Util;
import com.example.wlzz.utils.PhoneUtil;
import com.example.wlzz.utils.ResultVOUtil;
import com.example.wlzz.vo.ResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.*;
import java.net.URLDecoder;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 * 用户登陆注册页面
 * Created by 楠尼玛
 * 2018-03-31 16:20
 */
@RestController
@RequestMapping("/wlzzUser")
@Slf4j
@Api(tags = "注册登陆模块")
@CrossOrigin
public class UserController {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private UserService userService;
    @Autowired
    private ConfigAPI configAPI;
    @Autowired
    private SmsService smsService;
    @Autowired
    private FileApi fileApi;
    @ApiIgnore
    @GetMapping("/sayLovePage")
    public ModelAndView sayLoveForm() {
        return new ModelAndView("/saylove/saylove");
    }


    @PostMapping("/register")
    @ApiOperation("用户注册")
    public ResultVO register(@Valid UserForm userForm , BindingResult bindingResult){
    //    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    //   HttpServletRequest request = attributes.getRequest();
        log.info("userForm={}",userForm);
        if(bindingResult.hasErrors()) {
            log.info("userForm={}",userForm);
            log.error("register Error: result={}",bindingResult.getFieldError().getDefaultMessage());
            return ResultVOUtil.error(ResultEnum.REGISTER_ERROE.getCode(),ResultEnum.REGISTER_ERROE.getMessage());
        }
        //去redis查询
        String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, userForm.getToken()));
        log.info("【注册校验】redis的tokenValue={}",tokenValue);
        if (StringUtils.isEmpty(tokenValue)) {  //查询redis
            log.error("【注册校验】Redis中查不到token");
            return ResultVOUtil.error(ResultEnum.REDIS_FAIL.getCode(),ResultEnum.REDIS_FAIL.getMessage());
        }
        String[] array =  tokenValue.split(",");
        if(array[0].equals(userForm.getPhone())){    //这是匹配手机号码和验证码的
            if(array[1].equalsIgnoreCase(userForm.getCode())) {
                log.info("【注册校验】与redis的数据匹配成功");
                return userService.register(userForm);  //注册成功
            }
             else{
                return ResultVOUtil.error(ResultEnum.CODE_NO_ONLY.getCode(),ResultEnum.CODE_NO_ONLY.getMessage());
                }
            }else{
                 return ResultVOUtil.error(ResultEnum.REDIS_FAIL.getCode(),ResultEnum.REDIS_FAIL.getMessage());
            }
    }
    @PostMapping("/getSmsCode")
    @ApiOperation("【注册】获取手机验证码")
    public ResultVO getSmsCode(@ApiParam("手机号码") @RequestParam("phone")String phone){
        if(!PhoneUtil.getRightPhone(phone)){  //手机格式正则
            return ResultVOUtil.error(ResultEnum.PHONE_ERROR.getCode(),ResultEnum.PHONE_ERROR.getMessage());
        }
        User_ users = userService.findByPhone(phone);
            if(users!=null){
                log.warn("【注册校验】个人注册的手机号码重复，phone={}",phone);
                return ResultVOUtil.error(ResultEnum.PHONE_REPEAT.getCode(),ResultEnum.PHONE_REPEAT.getMessage());
          }
        //去redis查询是否该手机号码60秒内是否注册过
        String phoneToken = redisTemplate.opsForValue().get(String.format(RedisConstant.PHONE_PREFIX, phone));
        if (!StringUtils.isEmpty(phoneToken)) {  //查询redis
            log.error("【获取验证码】Redis查找到该手机号一分钟已申请过");
            return ResultVOUtil.error(ResultEnum.PHONE_COOLING.getCode(),ResultEnum.PHONE_COOLING.getMessage());
        }
        redisTemplate.opsForValue().set(String.format(RedisConstant.PHONE_PREFIX, phone), phone, RedisConstant.PHONE_EXPIRE, TimeUnit.SECONDS);
        String code = CodeUtil.getCode(); //验证码
        //设置验证码的token至redis
        String cookieToken = UUID.randomUUID().toString(); //token值
        Integer expire = RedisConstant.CODE_EXPIRE;  //验证码时长
        smsService.sendSms(phone,code);
        redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX, cookieToken), phone+","+code, expire, TimeUnit.SECONDS);
        TokenDTO tokenDTO = new TokenDTO();
        tokenDTO.setToken(cookieToken);
        return ResultVOUtil.success(tokenDTO);
    }
    @PostMapping("/exitLogin")
    @ApiOperation("【退出登陆】")
    public ResultVO exitLogin(@ApiParam("token") @RequestParam("token")String token){
        //去redis查询
        String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.LOGIN_SUCCESS_TOKEN, token));
        if (StringUtils.isEmpty(tokenValue)) {  //查询redis
            log.error("【切面登陆校验】Redis中查不到token");
            return ResultVOUtil.error(ResultEnum.NO_LOGIN.getCode(),ResultEnum.NO_LOGIN.getMessage());
        }
         redisTemplate.delete(String.format(RedisConstant.LOGIN_SUCCESS_TOKEN, token));
         return ResultVOUtil.success();
    }


    @PostMapping("/login")
    @ApiOperation("【登陆】")
    public ResultVO login(@Valid RegisterForm userForm ,BindingResult bindingResult){
        if(bindingResult.hasErrors()) {
            log.warn("userForm={}",userForm);
            return ResultVOUtil.error(ResultEnum.LOGIN_ERROR.getCode(),ResultEnum.LOGIN_ERROR.getMessage());
        }
        if(!PhoneUtil.getRightPhone(userForm.getPhone())){
            return ResultVOUtil.error(ResultEnum.PHONE_ERROR.getCode(),ResultEnum.PHONE_ERROR.getMessage());
        }
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        String token = attributes.getRequest().getHeader("token");
//            if(StringUtils.isEmpty(token)){
//                return ResultVOUtil.error(ResultEnum.LOGIN_ERROR.getCode(),ResultEnum.LOGIN_ERROR.getMessage());
//            }
//            //去redis查询
//            String codeToken = redisTemplate.opsForValue().get(String.format(RedisConstant.LOGIN_PREFIX,token));
//            if(!userForm.getCode().equalsIgnoreCase(codeToken)){
//                log.error("登陆验证码输入错误，userFormCode={},redisCode={}",userForm.getCode(),codeToken);
//                return ResultVOUtil.error(ResultEnum.CODE_ERROR.getCode(),ResultEnum.CODE_ERROR.getMessage());
//            }
            ResultVO resultVO = userService.login(userForm);
            return resultVO;
    }

    @ApiIgnore
    @GetMapping("/getImg")
    public void getImg(@RequestParam("flag") String flag) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = attributes.getResponse();
        FileInputStream fis = null;
        response.setContentType("image/*");
        try {
            OutputStream out = response.getOutputStream();
            File file = new File("/root/wlzz/taskImage"+ URLDecoder.decode(flag, "utf-8")+".jpg");
            fis = new FileInputStream(file);
            byte[] b = new byte[fis.available()];
            fis.read(b);
            out.write(b);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    @PostMapping("/getNoPasswordSms")
    @ApiOperation("【登陆】免密码登陆获取验证码")
    public ResultVO getNoPasswordSms(@ApiParam("手机号码") @RequestParam("phone")String phone){
        if(!PhoneUtil.getRightPhone(phone)){  //手机格式正则
            return ResultVOUtil.error(ResultEnum.PHONE_ERROR.getCode(),ResultEnum.PHONE_ERROR.getMessage());
        }
        User_ users = userService.findByPhone(phone);
        if(users==null){
            log.warn("【登陆校验】个人登陆的手机号码不存在，phone={}",phone);
            return ResultVOUtil.error(ResultEnum.PHONE_NOT_EXIST.getCode(),ResultEnum.PHONE_NOT_EXIST.getMessage());
        }
        //去redis查询是否该手机号码60秒内是否注册过
        String phoneToken = redisTemplate.opsForValue().get(String.format(RedisConstant.PHONE_PREFIX, phone));
        if (!StringUtils.isEmpty(phoneToken)) {  //查询redis
            log.error("【获取验证码】Redis查找到该手机号一分钟已申请过");
            return ResultVOUtil.error(ResultEnum.PHONE_COOLING.getCode(),ResultEnum.PHONE_COOLING.getMessage());
        }
        redisTemplate.opsForValue().set(String.format(RedisConstant.PHONE_PREFIX, phone), phone, RedisConstant.PHONE_EXPIRE, TimeUnit.SECONDS);
        String code = CodeUtil.getCode(); //测试验证码
        //设置验证码的token至redis
        String cookieToken = UUID.randomUUID().toString(); //token值
        Integer expire = RedisConstant.CODE_EXPIRE;  //验证码时长
        smsService.sendSms(phone,code);
        redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX, cookieToken), phone+","+code, expire, TimeUnit.SECONDS);
        TokenDTO tokenDTO = new TokenDTO();
        tokenDTO.setToken(cookieToken);
        return ResultVOUtil.success(tokenDTO);
    }

    @PostMapping("/modifyPasswordSms")
    @ApiOperation("【修改密码】修改密码，手机获取验证码")
    public ResultVO modifyPasswordSms(@ApiParam("该用户的手机号码") @RequestParam("phone")String phone){
          User_ users = userService.findByPhone(phone);
          if(users==null){
              log.error("用户不存在： phone={}",phone);
              return ResultVOUtil.error(ResultEnum.USER_NO_EXIST.getCode(),ResultEnum.USER_NO_EXIST.getMessage());
          }
          String cookieToken = UUID.randomUUID().toString(); //token值
          Integer expire = RedisConstant.CODE_EXPIRE;  //时长
            String code = CodeUtil.getCode(); //验证码
            redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX, cookieToken), phone+","+code, expire, TimeUnit.SECONDS);
            smsService.sendSms(phone,code);
            TokenDTO tokenDTO = new TokenDTO();
            tokenDTO.setToken(cookieToken);
            return ResultVOUtil.success(tokenDTO);
    }

    @PostMapping("/modifyPassword")
    @ApiOperation("【修改密码】修改密码,任何一项出错验证码失效")
    public ResultVO getNoPassword(@ApiParam("token") @RequestParam("token")String token,
                                    @ApiParam("新密码") @RequestParam("newPassword")String newPassword,
                                  @ApiParam("验证码") @RequestParam("code")String code){
        String codeToken = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, token));
        if (StringUtils.isEmpty(codeToken)) {  //查询redis
            log.error("【修改密码】Redis中查不到验证码token");
            redisTemplate.delete(String.format(RedisConstant.TOKEN_PREFIX, token));
            return ResultVOUtil.error(ResultEnum.CODE_ERROR.getCode(),ResultEnum.CODE_ERROR.getMessage());
        }
        String[] toeknArray = codeToken.split(",");
        if(!toeknArray[1].equals(code)){
            log.error("【修改密码】验证码不一致");
            redisTemplate.delete(String.format(RedisConstant.TOKEN_PREFIX, token));
            return ResultVOUtil.error(ResultEnum.CODE_ERROR.getCode(),ResultEnum.CODE_ERROR.getMessage());
        }
        User_ user = userService.findByPhone(toeknArray[0]);
        user.setPassword(MD5Util.EncoderByMd5(newPassword+user.getSalt()));
        userService.save(user);
        log.info("【修改密码】用户成功修改密码");
        return ResultVOUtil.success();
        }
    @PostMapping("/noPasswordLogin")
    @ApiOperation("【登陆】免密码登陆(验证码只可使用一次)")
    public ResultVO noPasswordLogin(@ApiParam("手机号码") @RequestParam(value = "phone",defaultValue = "")String phone,
                                    @ApiParam("验证码") @RequestParam("code")String code,
                                    @ApiParam("token") @RequestParam("token")String token){
        if(!PhoneUtil.getRightPhone(phone)){  //手机格式正则
            return ResultVOUtil.error(ResultEnum.PHONE_ERROR.getCode(),ResultEnum.PHONE_ERROR.getMessage());
        }
        User_ users = userService.findByPhone(phone);
        if(users==null){
            log.warn("【免密登陆校验】个人登陆的手机号码不存在，phone={}",phone);
            return ResultVOUtil.error(ResultEnum.PHONE_NOT_EXIST.getCode(),ResultEnum.PHONE_NOT_EXIST.getMessage());
        }
        //获取redis的值对比
        String phoneToken = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, token));
        if (StringUtils.isEmpty(phoneToken)) {  //查询redis
            log.error("【免密登陆校验】Redis查不到该redis值");
            return ResultVOUtil.error(ResultEnum.TOKEN_ERROR.getCode(),ResultEnum.TOKEN_ERROR.getMessage());
        }
        String[] array = phoneToken.split(",");
        if(!array[0].equals(phone)){  //手机号码对比
            log.error("【免密登陆校验】手机号码不一致");
            return ResultVOUtil.error(ResultEnum.PHONE_NO_ONLY.getCode(),ResultEnum.PHONE_NO_ONLY.getMessage());
        }
        if(!array[1].equalsIgnoreCase(code)){
            log.error("【免密登陆校验】验证码错误");
            redisTemplate.delete(String.format(RedisConstant.TOKEN_PREFIX, token));
            return ResultVOUtil.error(ResultEnum.CODE_NO_ONLY.getCode(),ResultEnum.CODE_NO_ONLY.getMessage());
        }
        String cookieToken = UUID.randomUUID().toString(); //token值
        Integer expire = RedisConstant.EXPIRE;  //登陆时长
        redisTemplate.opsForValue().set(String.format(RedisConstant.LOGIN_SUCCESS_TOKEN, cookieToken), phone, expire, TimeUnit.SECONDS);
        TokenDTO tokenDTO = new TokenDTO();
        tokenDTO.setToken(cookieToken);
        return ResultVOUtil.success(tokenDTO);
    }
    @ApiIgnore
    @GetMapping("/getCode")
    public void getImg(@RequestParam("number") String number,HttpServletResponse response)throws Exception{

        InputStream inputStream = new FileInputStream(fileApi.getSave_url()+number+".jpg");
        int i = inputStream.available();
        //byte数组用于存放图片字节数据
        byte[] buff = new byte[i];
        inputStream.read(buff);
        //记得关闭输入流
        inputStream.close();
        //设置发送到客户端的响应内容类型
        response.setContentType("image/*");
        OutputStream out = response.getOutputStream();
        out.write(buff);
        //关闭响应输出流
        out.close();
    }




}

